package logger

import (
	"errors"
	"fmt"
	"github.com/aliyun/alibabacloud-kms-agent/internal/conf"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"strings"
)

const (
	logName = "kms_agent.log"
)

var (
	InvalidLogLevelErrMsg = errors.New("invalid log level")
)

func formatLogLevel(str string) (level zapcore.Level, err error) {
	switch strings.ToLower(str) {
	case "debug":
		level = zap.DebugLevel
	case "info":
		level = zap.InfoLevel
	case "warn":
		level = zap.WarnLevel
	case "error":
		level = zap.ErrorLevel
	default:
		err = InvalidLogLevelErrMsg
	}
	return
}

type Logger struct {
	logger *zap.Logger
}

func NewLogger(cfg conf.LogConfig) (l *Logger, err error) {
	level, err := formatLogLevel(*cfg.LogLevel)
	if err != nil {
		return nil, err
	}
	lumberjackLogger := &lumberjack.Logger{
		Filename:   *cfg.LogPath + logName,
		MaxSize:    *cfg.MaxSize,
		MaxBackups: *cfg.MaxBackups,
	}

	ws := zapcore.AddSync(lumberjackLogger)

	eCfg := zap.NewProductionEncoderConfig()
	eCfg.EncodeTime = zapcore.RFC3339TimeEncoder
	enc := zapcore.NewJSONEncoder(eCfg)

	avl := zap.NewAtomicLevelAt(level)

	core := zapcore.NewCore(enc, ws, avl)

	logger := zap.New(core)
	defer logger.Sync()

	return &Logger{logger: logger}, nil
}

func (l *Logger) Debug(format string, v ...interface{}) {
	l.logger.Debug(fmt.Sprintf(format, v...))
}

func (l *Logger) Info(format string, v ...interface{}) {
	l.logger.Info(fmt.Sprintf(format, v...))
}

func (l *Logger) Warn(format string, v ...interface{}) {
	l.logger.Warn(fmt.Sprintf(format, v...))
}
func (l *Logger) Error(format string, v ...interface{}) {
	l.logger.Error(fmt.Sprintf(format, v...))
}
